home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / bsrc_p2.arc / ZRECEIVE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-30  |  42.1 KB  |  976 lines

  1. /*--------------------------------------------------------------------------*/
  2. /* FILE: zreceive.c (Opus zmodem receiver)                                  */
  3. /*                                                                          */
  4. /*                                                                          */
  5. /*               The Opus Computer-Based Conversation System                */
  6. /*       (c) Copyright 1986, Wynn Wagner III, All Rights Reserved           */
  7. /*                                                                          */
  8. /*      This implementation of Chuck Forsberg's ZMODEM protocol was         */
  9. /*              for Opus by Rick Huebner and Wynn Wagner III                */
  10. /*                                                                          */
  11. /* (MSC/4 with /Zp /Ox)                                                     */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*  This module is similar to a routine used by Opus-Cbcs (1.00).  It is    */
  17. /*  provided for your information only.  You will find routines that need   */
  18. /*  to be coded and identifiers to be resolved.                             */
  19. /*                                                                          */
  20. /*  There is absolutely no guarantee that anything here will work.  If you  */
  21. /*  break this routine, you own both pieces.                                */
  22. /*                                                                          */
  23. /*  USAGE:  You may use this material in any program with no obligation     */
  24. /*          as long as there is no charge for your program.  For more       */
  25. /*          information about commercial use, contact the "OPUSinfo HERE"   */
  26. /*          BBS (124/111).                                                  */
  27. /*                                                                          */
  28. /*  NOTE:   There are a couple of things the Opus implementation does that  */
  29. /*          aren't part of the original ZModem protocol.  They all deal     */
  30. /*          with WaZOO type ("ZedZap") netmail and should only show up when */
  31. /*          used under that condition.                                      */
  32. /*                                                                          */
  33. /*             * The maximum packet size can grow larger than 1k.  It is    */
  34. /*               sensitive to the baud rate.  (2400b=2048k; 9600b=8192k)    */
  35. /*             * The sender must be able to send nothing.  In other words,  */
  36. /*               the sending system must be able to initiate and terminate  */
  37. /*               a zmodem send session without having to actually send a    */
  38. /*               file.  Normally this kind of thing would never happen in   */
  39. /*               zmodem.                                                    */
  40. /*                                                                          */
  41. /*                                                                          */
  42. /*--------------------------------------------------------------------------*/
  43. #include "zmodem.h"
  44. #include "com.h"
  45. #include <sys/utime.h>
  46.  
  47. /*--------------------------------------------------------------------------*/
  48. /* External material                                                        */
  49. /*--------------------------------------------------------------------------*/
  50. extern int  dexists(byte *);
  51. extern long zfree (char *);
  52.  
  53. extern int  got_arcmail;
  54. extern int  got_bundle;
  55. extern int remote_capabilities;
  56. extern int  got_mail;
  57. extern int overwrite;
  58. extern int un_attended;
  59. extern int fullscreen;
  60.  
  61.  
  62. /*--------------------------------------------------------------------------*/
  63. /* Local routines                                                           */
  64. /*--------------------------------------------------------------------------*/
  65. int cdecl get_Zmodem(byte *,FILE *);
  66.  
  67. static int  pascal RZ_ReceiveData(byte *,int );
  68. static int  pascal RZ_InitReceiver(void);
  69. static int  pascal RZ_ReceiveBatch(FILE *);
  70. static int  pascal RZ_ReceiveFile(FILE *);
  71. static int  pascal RZ_GetHeader(void);
  72. static void pascal unique_name(byte *);
  73. static int  pascal RZ_SaveToDisk(unsigned long *);
  74. static void pascal RZ_AckBibi(void);
  75.  
  76.  
  77. /*--------------------------------------------------------------------------*/
  78. /* Private declarations                                                     */
  79. /*--------------------------------------------------------------------------*/
  80. static long DiskAvail;
  81. static long filetime;
  82. static byte realname[64];
  83.  
  84. /*--------------------------------------------------------------------------*/
  85. /* Private data                                                             */
  86. /*--------------------------------------------------------------------------*/
  87.  
  88. /* Parameters for ZSINIT frame */
  89. #define ZATTNLEN 32              /* Max length of attention string          */
  90.  
  91. static char  Attn[ZATTNLEN+1];   /* String rx sends to tx on err            */
  92. static FILE *Outfile;            /* Handle of file being received           */
  93. static byte *Secbuf;             /* Pointer to receive buffer               */
  94. static int   Tryzhdrtype;        /* Hdr type to send for Last rx close      */
  95. static char  isBinary;           /* Current file is binary mode             */
  96. static char  EOFseen;            /* indicates cpm eof (^Z) was received     */
  97. static char  Zconv;              /* ZMODEM file conversion request          */
  98. static int   RxCount;            /* Count of data bytes received            */
  99. static byte Resume_WaZOO;        /* Flags resumption of aborted WaZOO xfer  */
  100. static byte Resume_name[13];     /* "Real" name of file being received      */
  101. static byte Resume_info[48];     /* File size&time info for rx file         */
  102. static byte Abortlog_name[PATHLEN];  /* Path of WaZOO aborted xfer log      */
  103. static byte Upload_path[PATHLEN];    /* Dest. path of file being received   */
  104. static long Filestart;           /* File offset we started this xfer from   */
  105. extern long filelength();        /* returns length of file ref'd in stream  */
  106.  
  107.  
  108.  
  109. /*--------------------------------------------------------------------------*/
  110. /* GET ZMODEM                                                               */
  111. /* Receive a batch of files.                                                */
  112. /* returns TRUE (1) for good xfer, FALSE (0) for bad                        */
  113. /* can be called from f_upload or to get mail from a WaZOO Opus             */
  114. /*--------------------------------------------------------------------------*/
  115. int cdecl get_Zmodem(rcvpath, xferinfo)
  116.    byte *rcvpath;
  117.    FILE *xferinfo;
  118.    begin
  119.       byte        namebuf[PATHLEN];
  120.       int         i;
  121.       byte       *p;
  122.  
  123.       if (un_attended && fullscreen)
  124.          gotoxy (0,13);
  125.  
  126.       filetime = 0;
  127.       errno = 0;
  128.  
  129.       _BRK_DISABLE();
  130.       XON_ENABLE();
  131.       n_disable();
  132.  
  133.       Secbuf      = NULL;
  134.       Outfile     = NULL;
  135.       z_size      = 0;
  136.  
  137.       DiskAvail   = zfree("");
  138.  
  139.       Rxtimeout   = 100;
  140.       Tryzhdrtype = ZRINIT;
  141.       Secbuf      = zalloc();
  142.  
  143.       strcpy(namebuf, rcvpath);
  144.       Filename = namebuf;
  145.  
  146.       strcpy(Upload_path,rcvpath);
  147.       p  = Upload_path+strlen(Upload_path)-1;
  148.       while (p>=Upload_path && *p!='\\') --p;
  149.       *(++p) = '\0';
  150.  
  151.       sprintf(Abortlog_name, "%s%04x%04x.Z\0",
  152.        ctl.hold_area,remote_net,remote_node);
  153.  
  154.       if (((i=RZ_InitReceiver())==ZCOMPL) or
  155.           ((i==ZFILE) and ((RZ_ReceiveBatch(xferinfo))==OK)) )
  156.          begin
  157.             free(Secbuf);
  158.             return 1;
  159.          end
  160.  
  161.       CLEAR_OUTBOUND();
  162.       send_can();          /* transmit at least 10 cans */
  163.       wait_for_clear();
  164.  
  165.       if (Secbuf)    free(Secbuf);
  166.       if (Outfile)   fclose(Outfile);
  167.       return 0;
  168.  
  169.    end /* get_Zmodem */
  170.  
  171.  
  172.  
  173.  
  174.  
  175. /*--------------------------------------------------------------------------*/
  176. /* RZ RECEIVE DATA                                                          */
  177. /* Receive array buf of max length with ending ZDLE sequence                */
  178. /* and CRC.  Returns the ending character or error code.                    */
  179. /*--------------------------------------------------------------------------*/
  180. static int pascal RZ_ReceiveData(buf, length)
  181.    register byte *buf;
  182.    register int length;
  183.    begin
  184.       register int   c;
  185.       register word  crc;
  186.       int            d;
  187.  
  188.       crc   = RxCount   = 0;
  189.       buf[0] = buf[1] = 0;
  190.  
  191.       while(1)
  192.          begin
  193.             if ((c = Z_GetZDL()) & ~0xFF)
  194.                begin
  195. CRCfoo:
  196.                   switch (c)
  197.                      begin
  198.                         case GOTCRCE:
  199.                         case GOTCRCG:
  200.                         case GOTCRCQ:
  201.                         case GOTCRCW:  /*-----------------------------------*/
  202.                                        /* C R C s                           */
  203.                                        /*-----------------------------------*/
  204.                                        crc = Z_UpdateCRC(((d=c)&0xFF), crc);
  205.                                        if ((c=Z_GetZDL()) & ~0xFF) goto CRCfoo;
  206.  
  207.                                        crc = Z_UpdateCRC(c, crc);
  208.                                        if ((c=Z_GetZDL()) & ~0xFF) goto CRCfoo;
  209.  
  210.                                        crc = Z_UpdateCRC(c, crc);
  211.                                        if (crc & 0xFFFF)
  212.                                           begin
  213.                                              z_message( CRC_msg );
  214.                                              return ERROR;
  215.                                           end
  216.                                        return d;
  217.  
  218.                         case GOTCAN:   /*-----------------------------------*/
  219.                                        /* Cancel                            */
  220.                                        /*-----------------------------------*/
  221.                                        z_log(Cancelled_msg);
  222.                                        return ZCAN;
  223.  
  224.                         case TIMEOUT:  /*-----------------------------------*/
  225.                                        /* Timeout                           */
  226.                                        /*-----------------------------------*/
  227.                                        z_message( TIME_msg );
  228.                                        return c;
  229.  
  230.                         case RCDO:     /*-----------------------------------*/
  231.                                        /* No carrier                        */
  232.                                        /*-----------------------------------*/
  233.                                        z_log( CARRIER_msg );
  234.                                        return c;
  235.  
  236.                         default:       /*-----------------------------------*/
  237.                                        /* Something bizarre                 */
  238.                                        /*-----------------------------------*/
  239.                                        z_message("Debris");
  240.                                        cprintf(" [%x]",c);
  241.                                        CLEAR_INBOUND();
  242.                                        return c;
  243.                      end /* switch */
  244.                end /* if */
  245.  
  246.             if (--length < 0)
  247.                begin
  248.                   z_message("Long pkt");
  249.                   return ERROR;
  250.                end
  251.  
  252.             ++RxCount;
  253.             *buf++ = c;
  254.             crc = Z_UpdateCRC(c, crc);
  255.             continue;
  256.          end /* while(1) */
  257.  
  258.    end /* RZ_ReceiveData */
  259.  
  260.  
  261.  
  262. /*--------------------------------------------------------------------------*/
  263. /* RZ INIT RECEIVER                                                         */
  264. /* Initialize for Zmodem receive attempt, try to activate Zmodem sender     */
  265. /* Handles ZSINIT, ZFREECNT, and ZCOMMAND frames                            */
  266. /*                                                                          */
  267. /* Return codes:                                                            */
  268. /*    ZFILE .... Zmodem filename received                                   */
  269. /*    ZCOMPL ... transaction finished                                       */
  270. /*    ERROR .... any other condition                                        */
  271. /*--------------------------------------------------------------------------*/
  272. static int pascal RZ_InitReceiver()
  273.    begin
  274.       register int   n;
  275.       int            errors = 0;
  276.       char          *sptr;
  277.  
  278.  
  279.       for (n=10; --n>=0; )
  280.          begin
  281.  
  282.             /*--------------------------------------------------------------*/
  283.             /* Set buffer length (0=unlimited, don't wait).                 */
  284.             /* Also set capability flags                                    */
  285.             /*--------------------------------------------------------------*/
  286.             Z_PutLongIntoHeader(0L);
  287.             Txhdr[ZF0] = CANFDX|CANOVIO;
  288.             Z_SendHexHeader(Tryzhdrtype, Txhdr);
  289.             if (Tryzhdrtype == ZSKIP) Tryzhdrtype = ZRINIT;
  290.  
  291. AGAIN:
  292.  
  293.             switch (Z_GetHeader(Rxhdr))
  294.                begin
  295.                   case ZFILE:    /*-----------------------------------------*/
  296.                                  /*                                         */
  297.                                  /*-----------------------------------------*/
  298.                                  Zconv = Rxhdr[ZF0];
  299.                                  Tryzhdrtype = ZRINIT;
  300.                                  if (RZ_ReceiveData(Secbuf,WAZOOMAX)==GOTCRCW)
  301.                                     return ZFILE;
  302.                                  Z_SendHexHeader(ZNAK, Txhdr);
  303.                                  goto AGAIN;
  304.  
  305.                   case ZSINIT:   /*-----------------------------------------*/
  306.                                  /*                                         */
  307.                                  /*-----------------------------------------*/
  308.                                  if (RZ_ReceiveData(Attn, ZATTNLEN) == GOTCRCW)
  309.                                     Z_SendHexHeader(ZACK, Txhdr);
  310.                                  else Z_SendHexHeader(ZNAK, Txhdr);
  311.                                  goto AGAIN;
  312.  
  313.                   case ZFREECNT: /*-----------------------------------------*/
  314.                                  /*                                         */
  315.                                  /*-----------------------------------------*/
  316.                                  Z_PutLongIntoHeader(DiskAvail);
  317.                                  Z_SendHexHeader(ZACK, Txhdr);
  318.                                  goto AGAIN;
  319.  
  320.                   case ZCOMMAND: /*-----------------------------------------*/
  321.                                  /* Paranoia is good for you...             */
  322.                                  /* Ignore command from remote, but lie and */
  323.                                  /* say we did the command ok.              */
  324.                                  /*-----------------------------------------*/
  325.                                  if (RZ_ReceiveData(Secbuf,WAZOOMAX)==GOTCRCW)
  326.                                     begin
  327.                                        status_line("!Ignoring `%s'", Secbuf);
  328.                                        Z_PutLongIntoHeader(0L); 
  329.                                        do
  330.                                           begin
  331.                                              Z_SendHexHeader(ZCOMPL, Txhdr);
  332.                                           end
  333.                                        while (++errors<10 && Z_GetHeader(Rxhdr) != ZFIN);
  334.                                        RZ_AckBibi();
  335.                                        return ZCOMPL;
  336.                                     end
  337.                                  else Z_SendHexHeader(ZNAK, Txhdr);
  338.                                  goto AGAIN;
  339.  
  340.                   case ZCOMPL:   /*-----------------------------------------*/
  341.                                  /*                                         */
  342.                                  /*-----------------------------------------*/
  343.                                  goto AGAIN;
  344.  
  345.                   case ZFIN:     /*-----------------------------------------*/
  346.                                  /*                                         */
  347.                                  /*-----------------------------------------*/
  348.                                  RZ_AckBibi();
  349.                                  return ZCOMPL;
  350.  
  351.                   case ZCAN:     sptr  = CAN_msg;
  352.                                  goto Err;
  353.  
  354.                   case RCDO:     sptr  = CARRIER_msg;
  355.                                  goto Err;
  356.  
  357.                end /* switch */
  358.  
  359.          end /* for */
  360.  
  361.       sptr  = TIME_msg;
  362.  
  363. Err:
  364.       sprintf(e_input,"!Z-InitRecv %s",sptr);
  365.       z_log(e_input);
  366.  
  367.       return ERROR;
  368.  
  369.    end /* RZ_InitReceiver */
  370.  
  371.  
  372.  
  373.  
  374. /*--------------------------------------------------------------------------*/
  375. /* RZFILES                                                                  */
  376. /* Receive a batch of files using ZMODEM protocol                           */
  377. /*--------------------------------------------------------------------------*/
  378. static int pascal RZ_ReceiveBatch(xferinfo)
  379.    FILE *xferinfo;
  380.    begin
  381.       register int c;
  382.       FILE        *abortlog;
  383.       FILE        *newlog;
  384.       byte         linebuf[64];
  385.       byte         namebuf[PATHLEN];
  386.       byte        *p;
  387.  
  388. /*      set_xy("");*/
  389.       while(1)
  390.          begin
  391.             switch (c = RZ_ReceiveFile(xferinfo))
  392.                begin
  393.                   case ZEOF:
  394.                               if (Resume_WaZOO) {
  395.                                  errno = 0;
  396.                                  abortlog = fopen(Abortlog_name, read_ascii);
  397.                                  if (!got_error(OPEN_msg,Abortlog_name)) {
  398.                                     strcpy(namebuf,Abortlog_name);
  399.                                     strcpy(namebuf+strlen(namebuf)-1,"TMP");
  400.                                     errno = c = 0;
  401.                                     newlog = fopen(namebuf, write_ascii);
  402.                                     if (!got_error(OPEN_msg,namebuf)) {
  403.                                        while (!feof(abortlog)) {
  404.                                           linebuf[0] = '\0';
  405.                                           if (!fgets(linebuf,64,abortlog)) break;
  406.                                           p = linebuf;
  407.                                           while (*p > ' ') ++p;
  408.                                           *p = '\0';
  409.                                           if (stricmp(linebuf,Resume_name)) {
  410.                                              *p = ' ';
  411.                                              fputs(linebuf,newlog);
  412.                                              ++c;
  413.                                           }
  414.                                        }
  415.                                        fclose(abortlog);
  416.                                        fclose(newlog);
  417.                                        unlink(Abortlog_name);
  418.                                        if (c) rename(namebuf,Abortlog_name);
  419.                                        else unlink(namebuf);
  420.                                     } else fclose(abortlog);
  421.                                  }
  422.                                  strcpy(namebuf,Upload_path);
  423.                                  strcat(namebuf,Resume_name);
  424.                                  unique_name(namebuf);
  425.                                  rename(Filename,namebuf);
  426.                               }
  427.                               /* fallthrough */
  428.                   case ZSKIP:
  429.                               switch (RZ_InitReceiver())
  430.                                  begin
  431.                                     case ZCOMPL:   return OK;
  432.                                     default:       return ERROR;
  433.                                     case ZFILE:    break;
  434.                                  end /* switch */
  435.                               break;
  436.  
  437.                   default:
  438.                               fclose(Outfile);
  439.                               Outfile  = NULL;
  440.                               if (remote_capabilities) {
  441.                                  if (!Resume_WaZOO) {
  442.                                     strcpy(namebuf,Upload_path);
  443.                                     strcat(namebuf,"BadWaZOO.001");
  444.                                     unique_name(namebuf);
  445.                                     rename(Filename,namebuf);
  446.                                     errno = 0;
  447.                                     abortlog = fopen(Abortlog_name, "at");
  448.                                     if (!got_error(OPEN_msg,Abortlog_name)) {
  449.                                        fprintf(abortlog, "%s %s %s\n",
  450.                                         Resume_name,
  451.                                         namebuf+strlen(Upload_path),
  452.                                         Resume_info);
  453.                                        fclose(abortlog);
  454.                                     } else unlink(namebuf);
  455.                                  }
  456.                               } else unlink(Filename);
  457.                               errno    = 0;
  458.                               return c;
  459.                end /* switch */
  460.  
  461.          end /* while */
  462.  
  463.    end /* RZ_ReceiveBatch */
  464.  
  465.  
  466.  
  467.  
  468. /*--------------------------------------------------------------------------*/
  469. /* RZ RECEIVE FILE                                                          */
  470. /* Receive one file; assumes file name frame is preloaded in Secbuf         */
  471. /*--------------------------------------------------------------------------*/
  472. static int pascal RZ_ReceiveFile(xferinfo)
  473.    FILE *xferinfo;
  474.    begin
  475.       register int   c;
  476.       int            n;
  477.       long           rxbytes;
  478.       char        *sptr;
  479.       struct utimbuf utimes;
  480.  
  481.       EOFseen=FALSE;
  482.       if (RZ_GetHeader() == ERROR)  return (Tryzhdrtype = ZSKIP);
  483.  
  484.       n        = 10;
  485.       rxbytes  = Filestart;
  486.  
  487.       while(1)
  488.          begin
  489.             Z_PutLongIntoHeader(rxbytes);
  490.             Z_SendHexHeader(ZRPOS, Txhdr);
  491. NxtHdr:
  492.             switch (c = Z_GetHeader(Rxhdr))
  493.                begin
  494.                   case ZDATA:    /*-----------------------------------------*/
  495.                                  /* Data Packet                             */
  496.                                  /*-----------------------------------------*/
  497.                                  if (Rxpos != rxbytes)
  498.                                     begin
  499.                                        if ( --n < 0)
  500.                                           begin
  501.                                              sptr  = FUBAR_msg;
  502.                                              goto Err;
  503.                                           end
  504.                                        z_message(NULL);
  505.                                        cprintf("Bad pos; %ld/%ld",rxbytes,Rxpos);
  506.                                        Z_PutString(Attn);
  507.                                        continue;
  508.                                     end
  509. MoreData:
  510.                                  switch (c = RZ_ReceiveData(Secbuf,WAZOOMAX))
  511.                                     begin
  512.                                        case ZCAN:  sptr  = Cancelled_msg;
  513.                                                    goto Err;
  514.  
  515.                                        case RCDO:  sptr  = CARRIER_msg;
  516.                                                    goto Err;
  517.  
  518.                                        case ERROR: /*-----------------------*/
  519.                                                    /* CRC error             */
  520.                                                    /*-----------------------*/
  521.                                                    if (--n<0)
  522.                                                       begin
  523.                                                          sptr  = FUBAR_msg;
  524.                                                          goto Err;
  525.                                                       end
  526.                                                    show_loc(rxbytes,n);
  527.                                                    Z_PutString(Attn);
  528.                                                    continue;
  529.  
  530.                                        case TIMEOUT: /*---------------------*/
  531.                                                    /*                       */
  532.                                                    /*-----------------------*/
  533.                                                    if (--n<0)
  534.                                                       begin
  535.                                                          sptr  = TIME_msg;
  536.                                                          goto Err;
  537.                                                       end
  538.                                                    show_loc(rxbytes,n);
  539.                                                    continue;
  540.  
  541.                                        case GOTCRCW: /*---------------------*/
  542.                                                    /* End of frame          */
  543.                                                    /*-----------------------*/
  544.                                                    n = 10;
  545.                                                    if (RZ_SaveToDisk(&rxbytes)==ERROR)
  546.                                                       return ERROR;
  547.                                                    Z_PutLongIntoHeader(rxbytes);
  548.                                                    Z_SendHexHeader(ZACK, Txhdr);
  549.                                                    goto NxtHdr;
  550.  
  551.                                        case GOTCRCQ: /*---------------------*/
  552.                                                    /* Zack expected         */
  553.                                                    /*-----------------------*/
  554.                                                    n = 10;
  555.                                                    if (RZ_SaveToDisk(&rxbytes)==ERROR)
  556.                                                       return ERROR;
  557.                                                    Z_PutLongIntoHeader(rxbytes);
  558.                                                    Z_SendHexHeader(ZACK, Txhdr);
  559.                                                    goto MoreData;
  560.  
  561.                                        case GOTCRCG: /*---------------------*/
  562.                                                    /* Non-stop              */
  563.                                                    /*-----------------------*/
  564.                                                    n = 10;
  565.                                                    if (RZ_SaveToDisk(&rxbytes)==ERROR)
  566.                                                       return ERROR;
  567.                                                    goto MoreData;
  568.  
  569.                                        case GOTCRCE: /*---------------------*/
  570.                                                    /* Header to follow      */
  571.                                                    /*-----------------------*/
  572.                                                    n = 10;
  573.                                                    if (RZ_SaveToDisk(&rxbytes)==ERROR)
  574.                                                       return ERROR;
  575.                                                    goto NxtHdr;
  576.                                     end /* switch */
  577.  
  578.                   case ZNAK:
  579.                   case TIMEOUT:  /*-----------------------------------------*/
  580.                                  /* Packed was probably garbled             */
  581.                                  /*-----------------------------------------*/
  582.                                  if ( --n < 0)
  583.                                     begin
  584.                                        sptr  = "Garbled packet";
  585.                                        goto Err;
  586.                                     end
  587.                                  show_loc(rxbytes,n);
  588.                                  continue;
  589.  
  590.                   case ZFILE:    /*-----------------------------------------*/
  591.                                  /* Sender didn't see our ZRPOS yet         */
  592.                                  /*-----------------------------------------*/
  593.                                  RZ_ReceiveData(Secbuf, WAZOOMAX);
  594.                                  continue;
  595.  
  596.                   case ZEOF:     /*-----------------------------------------*/
  597.                                  /* End of the file                         */
  598.                                  /* Ignore EOF if it's at wrong place; force*/
  599.                                  /* a timeout because the eof might have    */
  600.                                  /* gone out before we sent our ZRPOS       */
  601.                                  /*-----------------------------------------*/
  602.                                  if (locate_y) gotoxy(0,(byte)locate_y-1);
  603.                                  if (Rxpos != rxbytes)  goto NxtHdr;
  604.  
  605.                                  throughput(2,rxbytes-Filestart);
  606.                                  errno = 0;
  607.  
  608.                                  fclose(Outfile);
  609.                                  got_error(CLOSE_msg,Filename);
  610.  
  611.                                  status_line("+Received-Z %s",realname);
  612.  
  613.                                  if (filetime)
  614.                                     begin 
  615.                                        utimes.actime = filetime;
  616.                                        utimes.modtime = filetime;
  617.                                        utime (Filename, &utimes);
  618.                                     end
  619.  
  620.                                  Outfile  = NULL;
  621.                                  if (xferinfo != NULL)
  622.                                     begin
  623.                                        fprintf(xferinfo, "%s\n", Filename);
  624.                                        got_error(WRITE_msg,"XferInfo");
  625.                                     end
  626.                                  return c;
  627.  
  628.                   case ERROR:    /*-----------------------------------------*/
  629.                                  /* Too much garbage in header search error */
  630.                                  /*-----------------------------------------*/
  631.                                  if ( --n < 0)
  632.                                     begin
  633.                                        sptr = "HdrJunk";
  634.                                        goto Err;
  635.                                     end
  636.                                  show_loc(rxbytes,n);
  637.                                  Z_PutString(Attn);
  638.                                  continue;
  639.  
  640.                   default:       /*-----------------------------------------*/
  641.                                  /*                                         */
  642.                                  /*-----------------------------------------*/
  643.                                  sptr  = IDUNNO_msg;
  644.                                  goto Err;
  645.  
  646.                end /* switch */
  647.  
  648.          end /* while */
  649.  
  650. Err:  sprintf(e_input,"!Z-rz %s",sptr);
  651.       z_log(e_input);
  652.       return ERROR;
  653.  
  654.    end /* RZ_ReceiveFile */
  655.  
  656.  
  657.  
  658. /*--------------------------------------------------------------------------*/
  659. /* RZ GET HEADER                                                            */
  660. /* Process incoming file information header                                 */
  661. /*--------------------------------------------------------------------------*/
  662. static int pascal RZ_GetHeader()
  663.    begin
  664.  
  665.       register byte *p, *q;
  666.       register int   n;
  667.       int i;
  668.  
  669.       byte          *ourname;
  670.       byte          *theirname;
  671.       unsigned long  filesize;
  672.       byte          *fileinfo;
  673.       FILE          *abortlog;
  674.       byte           linebuf[64];
  675.       byte          *badfile_name;
  676.       char          *strchr();
  677.  
  678.       /*--------------------------------------------------------------------*/
  679.       /* Setup the transfer mode                                            */
  680.       /*--------------------------------------------------------------------*/
  681.       isBinary  = (!RXBINARY && Zconv == ZCNL)? 0 : 1;
  682.       Resume_WaZOO = 0;
  683.  
  684.  
  685.       /*--------------------------------------------------------------------*/
  686.       /* Extract and verify filesize, if given.                             */
  687.       /* Reject file if not at least 10K free                               */
  688.       /*--------------------------------------------------------------------*/
  689.       filesize = 0L;
  690.       fileinfo = Secbuf + 1 + strlen(Secbuf);
  691.       if (*fileinfo) sscanf(fileinfo, "%ld %lo", &filesize, &filetime);
  692.       if (filesize+10240 > DiskAvail)
  693.          begin
  694.             status_line("!Disk space");
  695.             return ERROR;
  696.          end
  697.  
  698.       /*--------------------------------------------------------------------*/
  699.       /* Get and/or fix filename for uploaded file                          */
  700.       /*--------------------------------------------------------------------*/
  701.       p  = Filename+strlen(Filename)-1;     /* Find end of Opus upload path */
  702.       while (p>=Filename && *p!='\\') p--;
  703.       ourname = ++p;
  704.  
  705.       p = Secbuf+strlen(Secbuf)-1;      /* Find transmitted simple filename */
  706.       while (p >= Secbuf && *p!='\\' && *p!='/' && *p!=':') p--;
  707.       theirname = ++p;
  708.  
  709.  
  710.       strcpy(ourname,theirname);          /* Start w/ our path & their name */
  711.       strcpy(realname,Filename);
  712.  
  713.       /*--------------------------------------------------------------------*/
  714.       /* Save info on WaZOO transfer in case of abort                       */
  715.       /*--------------------------------------------------------------------*/
  716.       if (remote_capabilities) {
  717.          strcpy(Resume_name,theirname);
  718.          strcpy(Resume_info,fileinfo);
  719.       }
  720.  
  721.       /*--------------------------------------------------------------------*/
  722.       /* Check if this is a failed WaZOO transfer which should be resumed   */
  723.       /*--------------------------------------------------------------------*/
  724.       if (remote_capabilities && dexists(Abortlog_name))
  725.          begin
  726.             errno = 0;
  727.             abortlog = fopen( Abortlog_name, read_ascii );
  728.             if (!got_error(OPEN_msg,Abortlog_name))
  729.                begin
  730.                   while (!feof(abortlog))
  731.                      begin
  732.                         linebuf[0] = '\0';
  733.                         if (!fgets( (p=linebuf), 64, abortlog)) break;
  734.                         while (*p >= ' ') ++p;
  735.                         *p = '\0';
  736.                         p = strchr(linebuf,' ');
  737.                         *p = '\0';
  738.                         if (!stricmp(linebuf,theirname))
  739.                            begin
  740.                               p = strchr( (badfile_name = ++p), ' ');
  741.                               *p = '\0';
  742.                               if (!stricmp(++p,fileinfo))
  743.                                  begin
  744.                                     Resume_WaZOO = 1;
  745.                                     break;
  746.                                  end
  747.                            end
  748.                      end
  749.                   fclose(abortlog);
  750.                end
  751.          end
  752.  
  753.       /*--------------------------------------------------------------------*/
  754.       /* Open either the old or a new file, as appropriate                  */
  755.       /*--------------------------------------------------------------------*/
  756.       if (Resume_WaZOO) 
  757.          begin
  758.             strcpy(ourname,badfile_name);
  759.             p = "r+b";
  760.          end
  761.       else
  762.          begin
  763.             strcpy(ourname,theirname);
  764.             if (dexists(Filename))
  765.                begin                         /* If file already exists...      */
  766.                   i = strlen (Filename) - 1;
  767.                   if ((!overwrite) || (is_arcmail (Filename, i)))
  768.                      begin
  769.                         unique_name(Filename);
  770.                      end
  771.                   else
  772.                      begin
  773.                         unlink (Filename);
  774.                      end
  775.                end /* if exist */
  776.  
  777.             if (strcmp(ourname,theirname))
  778.                begin
  779.                   status_line("+Dupe renamed: %s",ourname);
  780.                   set_xy(NULL);
  781.                end
  782.             p = write_binary;
  783.          end
  784.       errno = 0;
  785.       Outfile = fopen( Filename, p);
  786.       if (got_error(OPEN_msg,Filename)) return ERROR;
  787.  
  788.       Filestart = (Resume_WaZOO)? filelength(fileno(Outfile)): 0L;
  789.       fseek(Outfile, Filestart, SEEK_SET);
  790.  
  791.  
  792.       if (remote_capabilities)
  793.          begin
  794.             p = theirname;
  795.             n  = strlen(p)-1;
  796.  
  797.             if ((p[n]=='t')&&(p[n-1]=='k')&&(p[n-2]=='p')&&(p[n-3]=='.'))
  798.                begin
  799.                   got_bundle  = 1;
  800.                   got_mail = 1;
  801.                   p           = "Bundle ";
  802.                end
  803.             else if (is_arcmail (p, n))
  804.                begin
  805.                   got_mail = 1;
  806.                   p           = "LZ-mail ";
  807.                end
  808.             else
  809.                begin
  810.                   got_mail = 1;
  811.                   p   = "NetFile ";
  812.                end
  813.          end
  814.       else p = NULL;
  815.  
  816.       if (un_attended && fullscreen)
  817.          {
  818.          clear_filetransfer();
  819.          gotoxy (0,13);
  820.          }
  821.       else
  822.          {
  823.          set_xy (NULL);
  824.          }
  825.       cprintf("%s %s; %s%ldb, %d min.",
  826.                   (p)? p: "Receiving",
  827.                   realname,
  828.                   (isBinary)? "": "ASCII ",
  829.                   filesize,
  830.                   (int)(filesize*10/cur_baud+27)/54);
  831.  
  832.       set_xy(NULL);
  833.  
  834.       throughput(0,0L);
  835.  
  836.       return OK;
  837.  
  838.    end /* RZ_GetHeader */
  839.  
  840.  
  841. /*--------------------------------------------------------------------------*/
  842. /* UNIQUE_NAME                                                              */
  843. /* Increments the suffix of a filename as necessary to make the name unique */
  844. /*--------------------------------------------------------------------------*/
  845. static void pascal unique_name(fname)
  846.    byte *fname;
  847.    begin
  848.       static byte suffix[] = ".001";
  849.       register char *p;
  850.       register int   n;
  851.  
  852.       if (dexists(fname))
  853.          begin                            /* If file already exists...      */
  854.             p = fname;
  855.             while (*p && *p!='.') p++;    /* ...find the extension, if any  */
  856.             for (n=0; n<4; n++)           /* ...fill it out if neccessary   */
  857.                if (!*p)
  858.                   begin
  859.                      *p       = suffix[n];
  860.                      *(++p)   = '\0';
  861.                   end
  862.                else p++;
  863.  
  864.             while (dexists(fname))       /* ...If 'file.ext' exists suffix++ */
  865.                begin
  866.                   p = fname+strlen(fname)-1;
  867.                   for (n=3; n--;)
  868.                      begin
  869.                         if (!isdigit(*p)) *p = '0';
  870.                         if (++(*p) <= '9') break;
  871.                         else *p-- = '0';
  872.                      end /* for */
  873.                end /* while */
  874.          end /* if exist */
  875.    end /* unique_name */
  876.  
  877.  
  878. /*--------------------------------------------------------------------------*/
  879. /* RZ SAVE TO DISK                                                          */
  880. /* Writes the received file data to the output file.                        */
  881. /* If in ASCII mode, stops writing at first ^Z, and converts all            */
  882. /*   solo CR's or LF's to CR/LF pairs.                                      */
  883. /*--------------------------------------------------------------------------*/
  884. static int pascal RZ_SaveToDisk(rxbytes)
  885.    unsigned long *rxbytes;
  886.    begin
  887.       static byte    lastsent;
  888.  
  889.       register byte *p;
  890.       register int   count;
  891.  
  892.       count = RxCount;
  893.  
  894.       if (((KEYPRESS()) and (READKB()==27)))
  895.          begin
  896.             send_can();                /* Cancel file */
  897.             while (Z_GetByte(20)!=TIMEOUT)    /* Wait for line to clear */
  898.         ;
  899.             send_can();                /* and Cancel Batch */
  900.             z_log( KBD_msg );
  901.             return ERROR;
  902.          end
  903.  
  904.       if (count!=z_size)
  905.          begin
  906.             gotoxy( locate_x+10, locate_y );
  907.             cputs( ultoa(((unsigned long )(z_size=count)),e_input,10) );
  908.             putch(' ');
  909.          end
  910.  
  911.       errno = 0;
  912.  
  913.       if (isBinary)
  914.          begin
  915.             fwrite( Secbuf, count, 1, Outfile );
  916.             if (errno) goto oops;
  917.          end
  918.       else
  919.          begin
  920.             if (EOFseen) return OK;
  921.             for (p=Secbuf; --count>=0; ++p )
  922.                begin
  923.                   if ( *p == CPMEOF)
  924.                      begin
  925.                         EOFseen = TRUE;
  926.                         return OK;
  927.                      end
  928.                   if ( *p=='\n' ) {
  929.                      if (lastsent!='\r' && putc('\r', Outfile) == EOF)
  930.                         goto oops;
  931.                   } else {
  932.                      if (lastsent=='\r' && putc('\n', Outfile) == EOF)
  933.                         goto oops;
  934.                   }
  935.                   if (putc((lastsent=*p), Outfile) == EOF)  goto oops;
  936.                end
  937.          end
  938.  
  939.       *rxbytes += RxCount;
  940.       
  941.       gotoxy( locate_x, locate_y );
  942.       cputs( ultoa(((unsigned long )(*rxbytes)),e_input,10) );
  943.       return OK; 
  944.  
  945. oops:
  946.       got_error(WRITE_msg,Filename);
  947.       return ERROR;
  948.  
  949.    end /* RZ_SaveToDisk */
  950.  
  951.  
  952.  
  953. /*--------------------------------------------------------------------------*/
  954. /* RZ ACK BIBI                                                              */
  955. /* Ack a ZFIN packet, let byegones be byegones                              */
  956. /*--------------------------------------------------------------------------*/
  957. static void pascal RZ_AckBibi()
  958.    begin
  959.       register int n;
  960.  
  961.       Z_PutLongIntoHeader(0L);
  962.       for (n=4; --n;)
  963.          begin
  964.             Z_SendHexHeader(ZFIN, Txhdr);
  965.             switch (Z_GetByte(100))
  966.                begin
  967.                   case 'O':      Z_GetByte(1);    /* Discard 2nd 'O' */
  968.  
  969.                   case TIMEOUT:
  970.                   case RCDO:     return;
  971.                end /* switch */
  972.          end /* for */
  973.  
  974.    end /* RZ_AckBibi */
  975.  
  976.